﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using HIWSystem.Common;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace HIWSystem.ViewModel
{
    public class TestSoftwareManageViewModel : ViewModelBase
    {
        #region 字段
        private object _mutex = new object();//异步锁
        private bool isFirstFilterSoftware = true;//是第一次过滤软件名称
        private ObservableCollection<string> backupSoftwares;//备份软件集
        private bool isFirstFilterVersion = true;//是第一次过滤版本
        private ObservableCollection<string> backupVersions;//备份软件集
        #endregion

        #region 属性

        private ObservableCollection<string> softwares;

        /// <summary>
        /// 软件集合
        /// </summary>
        public ObservableCollection<string> Softwares
        {
            get { return softwares; }
            set { softwares = value; this.RaisePropertyChanged(() => Softwares); }
        }

        private string selectedSoftware;

        /// <summary>
        /// 选择的软件
        /// </summary>
        public string SelectedSoftware
        {
            get { return selectedSoftware; }
            set { selectedSoftware = value; this.RaisePropertyChanged(() => SelectedSoftware); }
        }

        private bool isOpenComboSoftwareDropDown;

        /// <summary>
        /// 是否展开软件下拉框选项卡
        /// </summary>
        public bool IsOpenComboSoftwareDropDown
        {
            get { return isOpenComboSoftwareDropDown; }
            set { isOpenComboSoftwareDropDown = value; this.RaisePropertyChanged(() => IsOpenComboSoftwareDropDown); }
        }

        private string searchSoftwareText;

        /// <summary>
        /// 软件下拉框中输入的文本内容
        /// </summary>
        public string SearchSoftwareText
        {
            get { return searchSoftwareText; }
            set { searchSoftwareText = value; this.RaisePropertyChanged(() => SearchSoftwareText); }
        }

        private ObservableCollection<string> versions;

        /// <summary>
        /// 版本集合
        /// </summary>
        public ObservableCollection<string> Versions
        {
            get { return versions; }
            set { versions = value; this.RaisePropertyChanged(() => Versions); }
        }

        private string selectedVersion;

        /// <summary>
        /// 选择的版本
        /// </summary>
        public string SelectedVersion
        {
            get { return selectedVersion; }
            set { selectedVersion = value; this.RaisePropertyChanged(() => SelectedVersion); }
        }

        private bool isOpenComboVsersionDropDown;

        /// <summary>
        /// 是否展开版本下拉框选项卡
        /// </summary>
        public bool IsOpenComboVersionDropDown
        {
            get { return isOpenComboVsersionDropDown; }
            set { isOpenComboVsersionDropDown = value; this.RaisePropertyChanged(() => IsOpenComboVersionDropDown); }
        }

        private string searchVersionText;

        /// <summary>
        /// 版本下拉框中输入的文本内容
        /// </summary>
        public string SearchVersionText
        {
            get { return searchVersionText; }
            set { searchVersionText = value; this.RaisePropertyChanged(() => SearchVersionText); }
        }

        private ObservableCollection<string> executableFiles;

        /// <summary>
        /// 可执行文件集合
        /// </summary>
        public ObservableCollection<string> ExecutableFiles
        {
            get { return executableFiles; }
            set { executableFiles = value; this.RaisePropertyChanged(() => ExecutableFiles); }
        }

        private double downloadProgressValue;

        /// <summary>
        /// 下载进度值
        /// </summary>
        public double DownloadProgressValue
        {
            get { return downloadProgressValue; }
            set { downloadProgressValue = value; this.RaisePropertyChanged(() => DownloadProgressValue); }
        }

        private double downloadProgressMaximum;
        /// <summary>
        /// 下载的最大值
        /// </summary>
        public double DownloadProgressMaximum
        {
            get { return downloadProgressMaximum; }
            set { downloadProgressMaximum = value; this.RaisePropertyChanged(() => DownloadProgressMaximum); }
        }

        #endregion 属性

        #region 命令

        private RelayCommand loadedPageCmd;

        public RelayCommand LoadedPageCmd
        {
            get { return loadedPageCmd ?? new RelayCommand(LoadedPage); }
            set { loadedPageCmd = value; }
        }

        private RelayCommand filterSoftwareCmd;

        public RelayCommand FilterSoftwareCmd
        {
            get { return filterSoftwareCmd ?? new RelayCommand(FilterSoftware); }
            set { filterSoftwareCmd = value; }
        }

        private RelayCommand<string> softwareSelectionChangedEvent;

        public RelayCommand<string> SoftwareSelectionChangedEvent
        {
            get { return softwareSelectionChangedEvent ?? new RelayCommand<string>(SoftwareSelectionChangedHandler); }
            set { softwareSelectionChangedEvent = value; }
        }

        private RelayCommand filterVersionCmd;

        public RelayCommand FilterVersionCmd
        {
            get { return filterVersionCmd ?? new RelayCommand(FilterVersion); }
            set { filterVersionCmd = value; }
        }

        private RelayCommand downloadCmd;

        public RelayCommand DownloadCmd
        {
            get { return downloadCmd ?? new RelayCommand(Download); }
            set { downloadCmd = value; }
        }

        private RelayCommand<string> executableFileSelectedChangedEvent;

        public RelayCommand<string> ExecutableFileSelectedChangedEvent
        {
            get { return executableFileSelectedChangedEvent ?? new RelayCommand<string>(ExecuteFileSelectedChangedHandler); }
            set { executableFileSelectedChangedEvent = value; }
        }

        #endregion 命令

        #region 方法

        /// <summary>
        /// 页面加载
        /// </summary>
        private void LoadedPage()
        {
            FetchSoftwares();
        }

        private void FetchSoftwares()
        {
            var softwares = Directory.GetDirectories(Global.AppConfigs.ProductionSoftwareInfo.RemotePath).Select(d => d.Substring(d.LastIndexOf('\\') + 1)).Distinct().ToList();
            Softwares = new ObservableCollection<string>();
            foreach (var s in softwares)
            {
                Softwares.Add(s);
            }
        }

        /// <summary>
        /// 过滤软件
        /// </summary>
        private void FilterSoftware()
        {
            IsOpenComboSoftwareDropDown = true;
            //当是第一次过滤的时候备份原始数据
            //这样是为了当不输入搜索条件时添加原始数据到列表中
            //当输入搜索条件时生成过滤集合绑定当下拉列表中
            if (isFirstFilterSoftware)
            {
                backupSoftwares = new ObservableCollection<string>();
                backupSoftwares = Softwares;
                isFirstFilterSoftware = false;
            }
            if (!string.IsNullOrEmpty(SearchSoftwareText))
            {
                IEnumerable<string> searchSoftwares = Softwares.Where(s => s.ToUpper().Contains(SearchSoftwareText.ToUpper()));
                Softwares = new ObservableCollection<string>();
                foreach (var s in searchSoftwares)
                {
                    Softwares.Add(s);
                }
            }
            else
            {
                Softwares = backupSoftwares;
            }
        }

        /// <summary>
        /// 过滤版本
        /// </summary>
        private void FilterVersion()
        {
            IsOpenComboVersionDropDown = true;
            //当是第一次过滤的时候备份原始数据
            //这样是为了当不输入搜索条件时添加原始数据到列表中
            //当输入搜索条件时生成过滤集合绑定当下拉列表中
            if (isFirstFilterVersion)
            {
                backupVersions = new ObservableCollection<string>();
                backupVersions = Versions;
                isFirstFilterVersion = false;
            }
            if (!string.IsNullOrEmpty(SearchVersionText))
            {
                IEnumerable<string> searchVersions = Versions.Where(s => s.ToUpper().Contains(SearchVersionText.ToUpper()));
                Versions = new ObservableCollection<string>();
                foreach (var v in searchVersions)
                {
                    Versions.Add(v);
                }
            }
            else
            {
                Versions = backupVersions;
            }
        }

        /// <summary>
        /// 测试软件下载
        /// </summary>
        private void Download()
        {
            IProgress<double> progress = new Progress<double>(ReportProgress);
            _ = StartDownloadAsync(progress);
        }
        /// <summary>
        /// 报告下载进度
        /// </summary>
        /// <param name="value">进度值</param>
        private void ReportProgress(double value)
        {
            Application.Current.Dispatcher.Invoke((Action)(()=> {

                DownloadProgressValue = value;
            }));
        }

        private async Task StartDownloadAsync(IProgress<double> progress, CancellationToken token=default(CancellationToken))
        {
            if (!CheckSelectedCondition())
            {
                return;
            }
            try
            {
                var targetFolder = Path.Combine(Global.AppConfigs.ProductionSoftwareInfo.RemotePath, string.Format($"{SelectedSoftware}\\{SelectedVersion}"));
                var targetFiles = Directory.GetFiles(targetFolder,"*",SearchOption.AllDirectories);
                ExecutableFiles = new ObservableCollection<string>();
                double progressValue = 0, progressPercent = 0;
                DownloadProgressMaximum = targetFiles.Count();
                await Task.Run(() =>
                {
                    Parallel.ForEach(targetFiles, new ParallelOptions { CancellationToken = token }, (source, state, index) =>
                    {
                        //处理每个文件
                        ProcessFile(source);
                        lock (_mutex)
                        {
                            ++progressValue;
                            Trace.WriteLine(progressValue);
                            //progressValue/ DownloadProgressMaximum);
                            Trace.WriteLine(progressValue);
                        }
                        //报告进度
                        progress.Report(progressValue);
                    });
                });
                MessageBoxService("下载成功!", MessageBoxImage.Information);
            }
            catch (AggregateException ex)
            {
                StringBuilder errorMessage = new StringBuilder();
                foreach (var innerEx in ex.InnerExceptions)
                {
                    errorMessage.Append(innerEx.Message);
                }
                MessageBoxService(errorMessage.ToString(), MessageBoxImage.Error);
            }
            catch (Exception ex)
            {
                MessageBoxService(ex.Message,MessageBoxImage.Error);
            }
        }
        /// <summary>
        /// 处理每个文件
        /// </summary>
        /// <returns></returns>
        private void ProcessFile(string filename)
        {
            try
            {
                var dir = Path.GetDirectoryName(filename);
                var extension = Path.GetExtension(filename);
                if (!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }

                var fileLocalSavePath = filename.Replace(Global.AppConfigs.ProductionSoftwareInfo.RemotePath, Global.AppConfigs.ProductionSoftwareInfo.LocalPath);
                if (!Directory.Exists(Path.GetDirectoryName(fileLocalSavePath)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(fileLocalSavePath));
                }
                if (extension.Equals(".exe"))
                {
                    RecordExecutableFile(fileLocalSavePath);
                }
                //拷贝文件到本地
                File.Copy(filename, fileLocalSavePath, true);
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("下载单个文件的时候出现错误:【｛0｝】",ex.Message));
            }
          
        }
        /// <summary>
        /// 添加可执行文件到列表框中
        /// </summary>
        /// <param name="filename">文件</param>
        private void RecordExecutableFile(string filename)
        {
            Application.Current.Dispatcher.Invoke((Action)(() => {
                ExecutableFiles.Add(filename);
            }));
        }
        /// <summary>
        /// 检查筛选的条件
        /// </summary>
        /// <returns></returns>
        private bool CheckSelectedCondition()
        {
            if ((SelectedSoftware ?? "") == "" || (SelectedVersion ?? "") == "")
            {
                MessageBoxService("请检查是否已经选择了软件和版本信息?", MessageBoxImage.Warning);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 提示窗口服务
        /// </summary>
        /// <param name="message">信息</param>
        /// <param name="icon">提示图标</param>
        private void MessageBoxService(string message, MessageBoxImage icon)
        {
            MessageBox.Show(message, "软件温馨提示", MessageBoxButton.OK, icon);
        }

        //软件选择改变事件处理程序
        private void SoftwareSelectionChangedHandler(string software)
        {
            if (software != null)
            {
                var verionFolder = Path.Combine(Global.AppConfigs.ProductionSoftwareInfo.RemotePath, software);
                var versions = Directory.GetDirectories(verionFolder).Select(d => Path.GetFileName(d)).OrderByDescending(v => v);
                Versions = new ObservableCollection<string>();
                foreach (var v in versions)
                {
                    Versions.Add(v);
                }
            }
        }

        /// <summary>
        /// 测试软件文件选中事件处理程序
        /// </summary>
        /// <param name="obj"></param>
        private void ExecuteFileSelectedChangedHandler(string obj)
        {
            if (obj!=null)
            {
                ProcessStartInfo startInfo = new ProcessStartInfo {
                    FileName = obj,
                    WorkingDirectory = Path.GetDirectoryName(obj), // 设置工作路径为exe所在目录
                    UseShellExecute = true // 使用外壳程序执行
                };
                Process process = Process.Start(startInfo);
            }
        }

        #endregion 方法
    }
}